package util;

import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.QuadCurve2D.Double;


public class LinAlg {
	public static Point normalize(Point p) {
		return new Point((p.getX() / p.distance(new Point(0, 0))), 
				(p.getY() / p.distance(new Point(0, 0))));
	}
	public static Point scale(Point p, double scaler) {
		return new Point(p.getX() * scaler, p.getY() * scaler);
	}
	public static Point unitVectorBetween(Point p1, Point p2) {
		double newX = p1.getX() - p2.getX();
		double newY = p1.getY() - p2.getY();
		return normalize(new Point(newX, newY));
	}

	public static Point diff(Point p1, Point p2) {
		return new Point(p1.getX() - p2.getX(), p1.getY() - p2.getY());
	}
	
	public static Point unitVector(Point p) {
		return new Point(p.getX() / mag(p), p.getY() / mag(p));
	}
	
	public static double mag(Point p) {
		return p.getX() * p.getX() + p.getY() * p.getY();
	}

	public static Point trans(Point p1, Point p2) {
		return new Point(p1.getX() + p2.getX(), p1.getY() + p2.getY());
	}

	public static Polygon rotate(Polygon p, double angle) {
		int[] xPoints = p.xpoints;
		int[] yPoints = p.ypoints;
		int[] newX = new int[p.npoints];
		int[] newY = new int[p.npoints];
		for(int i =0; i < xPoints.length; i++) {
			newX[i] = (int) (xPoints[i] * Math.cos(angle) + yPoints[i] * -Math.sin(angle));
			newY[i] = (int) (xPoints[i] * Math.sin(angle) + yPoints[i] * Math.cos(angle));
		}
		return new Polygon(newX, newY, p.npoints);
	}

	public static Polygon rotate(Rectangle2D.Double p, double angle) {
		double[] xPoints = { p.getX(), p.getX() + p.getWidth(), p.getWidth(), p.getX() };
		double[] yPoints = { p.getY(), p.getY(), p.getY() + p.getHeight(), p.getY() + p.getHeight()};
		int[] newX = new int[4];
		int[] newY = new int[4];
		for(int i =0; i < xPoints.length; i++) {
			newX[i] = (int) (xPoints[i] * Math.cos(angle) + yPoints[i] * -Math.sin(angle));
			newY[i] = (int) (xPoints[i] * Math.sin(angle) + yPoints[i] * Math.cos(angle));
		}
		return new Polygon(newX, newY, 4);
	}


	/**
	 * Determines if the two polygons supplied intersect each other, by checking if either polygon has points which are contained in the other.
	 * (It doesn't detect body-only intersections, but is sufficient in most cases.)
	 */
	public static boolean intersect(Shape s1, Shape s2) 
	{
		if(s1 instanceof Line2D.Double) {
			return s1.intersects(s2.getBounds2D());
		}
		if(s2 instanceof Line2D.Double) {
			return s2.intersects(s2.getBounds2D());
		}
		PathIterator p = s1.getPathIterator(new AffineTransform());
		double[] cords = new double[6];
		while(! p.isDone()) {
			p.currentSegment(cords);
			if(s2.contains(new Point2D.Double(cords[0], cords[1]))) {
				return true;
			}
			p.next();
		}

		p = s2.getPathIterator(new AffineTransform());
		while(! p.isDone()) {
			p.currentSegment(cords);
			if(s1.contains(new Point2D.Double(cords[0], cords[1]))) {
				return true;
			}
			p.next();
		}
		return false;
	}
	
	
	/**
	 * Checks to see if two shape arrays have hit each other.
	 * @param s
	 * @param s1
	 * @return
	 */
	public static boolean checkCollide(Shape[] s, Shape[] s1) {
		for(int i = 0; i < s.length; i++) {
			for(int j = 0; j < s1.length; j++) {
				if(LinAlg.intersect(s[i], s1[j])) {
					return true;
				}
			}
		}
		return false;
	}
}
